USB interface programming example.
Win98, Win2K Pro/Server, C3000Z/C3030Z, !!! WILL NOT work with 3040Z !!!


Camera has 2 interfaces - one is for receiving and the other one for sending data.To access camera we have to open 2 pipes respectively. Pipe name combines the device name link + PIPE01 for receiving end or PIPE00 for sending end. The device name link can be obtained from the registry. As soon as camera plugged in, the OS sets its value in the registry as follows (Win2K Pro):

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\Vid_07b4&Pid_0100\4&9be3f2d&0&2]
"DeviceDesc"="OLYMPUS Digital Camera"
"LocationInformation"="C-3000ZOOM"
"Capabilities"=dword:00000004
"HardwareID"=hex(7):55,53,42,5c,56,69,64,5f,30,37,62,34,26,50,69,64,5f,30,31,\
  30,30,26,52,65,76,5f,30,31,30,30,00,55,53,42,5c,56,69,64,5f,30,37,62,34,26,\
  50,69,64,5f,30,31,30,30,00,00
"CompatibleIDs"=hex(7):55,53,42,5c,43,6c,61,73,73,5f,66,66,26,53,75,62,43,6c,\
  61,73,73,5f,66,66,26,50,72,6f,74,5f,66,66,00,55,53,42,5c,43,6c,61,73,73,5f,\
  66,66,26,53,75,62,43,6c,61,73,73,5f,66,66,00,55,53,42,5c,43,6c,61,73,73,5f,\
  66,66,00,00
"ClassGUID"="{36FC9E60-C465-11CF-8056-444553540000}"
"Class"="USB"
"Driver"="{36FC9E60-C465-11CF-8056-444553540000}\\0006"
"Mfg"="OLYMPUS"
"Service"="OlCamudp"
"ConfigFlags"=dword:00000000

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\Vid_07b4&Pid_0100\4&9be3f2d&0&2\Device Parameters]
"SymbolicName"="\\??\\USB#Vid_07b4&Pid_0100#4&9be3f2d&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\Vid_07b4&Pid_0100\4&9be3f2d&0&2\LogConf]

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\Vid_07b4&Pid_0100\4&9be3f2d&0&2\Control]
"ActiveService"="OlCamudp"
"DeviceReference"=dword:8112d0b0
The key location and value notation are differrent under Win 98:
[HKEY_LOCAL_MACHINE\Enum\USB\VID_07B4&PID_0100\1USB&ROOT_HUB&PCI&VEN_1045&DEV_C861&SUBSYS_F8B00E11&REV_10&BUS_00&DEV_13&FUNC_00]
"Capabilities"=hex:04,00,00,00
"HardwareID"="USB\\VID_07B4&PID_0100&REV_0100,USB\\VID_07B4&PID_0100"
"CompatibleIDs"="USB\\CLASS_FF&SUBCLASS_FF&PROT_FF,USB\\CLASS_FF&SUBCLASS_FF,USB\\CLASS_FF"
"DeviceDesc"="OLYMPUS Digital Camera"
"Class"="USB"
"ConfigFlags"=hex:00,00,00,00
"Driver"="USB\\0002"
"Mfg"="OLYMPUS"
"ClassGUID"="{36FC9E60-C465-11CF-8056-444553540000}"
"Serial"=hex:05,00,00,00,00,00,00,00
"SymbolicName"="\\DosDevices\\0000000000000005#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"

Olympus camera can be identified by DeviceDesc value "OLYMPUS Digital Camera" The fully defined pipe names for my machine are as following:

Win2k Pro/Server:

pipeIN  = "\\\\.\\USB#Vid_07b4&Pid_0100#4&9be3f2d&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}\\PIPE01";
pipeOUT = "\\\\.\\USB#Vid_07b4&Pid_0100#4&9be3f2d&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}\\PIPE00";

Win 98:
pipeIN  = "\\\\.\\0000000000000005#{a5dcbf10-6530-11d2-901f-00c04fb951ed}\\PIPE01";
pipeOUT = "\\\\.\\0000000000000005#{a5dcbf10-6530-11d2-901f-00c04fb951ed}\\PIPE00";

Then you can open pipes and communicate with camera by writing an reading data directly to pipes. You can use protocol description (see links) as the guide, but it is not full and contains some incorrect information. The better way is to examine actual Olcamapi.dll code. Its quite easy to read, so you will have plenty of fun ))
// This code section is an adapted version of the example program
// that displays the currently attached USB devices using
// the dynamic Registry entries
// The original version can be found at the http://www.USB-By-Example.com
// This example is coded for Win98 , but can be easily modified to suit Win2K - see info on key values above.

void CTestDlg::OnButton1()
{
char    OLYCAM_DEVICENAME[255] = "OLYMPUS Digital Camera";
char    PIPE_IN[255];
char    PIPE_OUT[255];
HANDLE  hcamOUT;
HANDLE  hcamIN;


PCHAR   LinkName;
int     LinkNameSize=256;
DWORD   bytesdone;
char    buf[2050];
long    cs;
int     i;


LinkName = (char *) malloc(     LinkNameSize);
i = GetDeviceLink( OLYCAM_DEVICENAME, LinkName, LinkNameSize );

strcpy( PIPE_IN, LinkName);
strcpy( PIPE_OUT, LinkName);
strcat( PIPE_IN,"\\PIPE00");
strcat( PIPE_OUT,"\\PIPE01");

hcamIN = CreateFile(PIPE_IN,
                  GENERIC_READ,
                  FILE_SHARE_READ,
                  NULL, // no SECURITY_ATTRIBUTES structure
                  OPEN_EXISTING, // No special create flags
                  0, // No special attributes
                  NULL); // No template file

hcamOUT = CreateFile(PIPE_OUT,
                  GENERIC_WRITE ,
                  FILE_SHARE_WRITE,
                  NULL, // no SECURITY_ATTRIBUTES structure
                  OPEN_EXISTING, // No special create flags
                  0, // No special attributes
                  NULL); // No template file

// If the handles are valid, then we've successfully opened the pipes
if ((hcamIN != INVALID_HANDLE_VALUE) && (hcamOUT != INVALID_HANDLE_VALUE)) {

//      02 02 00: push shutter button
//      CPU: 1B 'C' 03 00 02 02 00 CS CS
//      CAM:                             06
//
//      Don't know what happens if the command is issued while the memory
//      is full.  (should check before with series 'C' 01 0B)

        cs = 0;
        i=0;
        buf[i++] = 0x1B;
        buf[i++] = 'C';
        buf[i++] = 03;
        buf[i++] = 00;
        buf[i++] = 02;
        buf[i++] = 02;
        buf[i++] = 00;
        for (i=4; i<7; i++) {
         cs+= (UINT) buf[i];
        }
        cs = cs & 0xFFFF;
        buf[7] = char (cs & 0xFF);
        buf[8] = char (cs / 0xFF);


        if (!WriteFile( hcamOUT, buf, 9, &bytesdone, 0 )) {
         bytesdone = GetLastError();
        }

        if (!ReadFile( hcamIN, buf, 1, &bytesdone,0)) {
         bytesdone = GetLastError();
        }

        }

}


BOOL GetDeviceLink( PCHAR DeviceDescription,
                        PCHAR LinkName,
                        int LinkNameLen)
{
long status;
HKEY KeyHandle, SubKeyHandle, HardWareHandle;
DWORD KeyCount, index, i, SubKeyNameSize, HardWareKeyValueSize, DeviceDescSize;
char SubKeyName[255];
char HardWareKeyValue[255] = "Enum\\"; // Preset the first 5 characters
char DevDesc[255];
char* NamePtr;
//      char LinkName[255];
FILETIME FileTime;


// Perform parameters check
        if ((DeviceDescription == NULL) || (LinkName== NULL) || (LinkNameLen ==0)) return -1;
// Start searching the registry for currently enumerated devices
        status = RegOpenKeyEx(HKEY_DYN_DATA, "Config Manager\\Enum", 
					0, KEY_QUERY_VALUE, &KeyHandle);
        if (status != 0) return FALSE;
// How many sub keys are there?
        status = RegQueryInfoKey(KeyHandle, NULL, NULL, NULL, &KeyCount, 
					NULL, NULL, NULL, NULL, NULL, NULL, NULL);
        if (status != 0) return FALSE;
        for (index=0; index<KeyCount; index++) {
// What is the sub key name?
                SubKeyNameSize = 255; NamePtr = &SubKeyName[0];
                status = RegEnumKeyEx(KeyHandle, index, NamePtr, &
					SubKeyNameSize, NULL, NULL, NULL, &FileTime);
                if (status != 0) return FALSE;
// Open the sub key
                status = RegOpenKeyEx(KeyHandle, NamePtr, 0, KEY_QUERY_VALUE,
					 &SubKeyHandle);
                if (status != 0) return FALSE;
// Get the Value for the HardWareKey of this sub key
                HardWareKeyValueSize = 255; NamePtr = &HardWareKeyValue[5];
                status = RegQueryValueEx(SubKeyHandle, "HardWareKey", NULL, NULL, 
					(BYTE*)NamePtr, &HardWareKeyValueSize);
                if (status != 0) return FALSE;
                status = RegCloseKey(SubKeyHandle);
                if (status != 0) return FALSE;
// Look for USB devices
                if ((HardWareKeyValue[5] == 'U')&&(HardWareKeyValue[6] == 'S')
				&&(HardWareKeyValue[7] == 'B')) {
                        i = 9; // Display VID, PID information
                        //while (HardWareKeyValue[i] != '\\')
                        //      WindowText[WindowIndex++] = HardWareKeyValue[i++];
                        //WindowText[WindowIndex++] = '=';
// Get Configuration Information about this USB device
                        status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, &HardWareKeyValue[0], 
				0, KEY_QUERY_VALUE, &HardWareHandle);
                        if (status != 0) return FALSE;
                        DeviceDescSize = 255; NamePtr = &DevDesc[0];
                        status = RegQueryValueEx(HardWareHandle, "DeviceDesc", NULL, NULL, 
					(BYTE*)NamePtr, &DeviceDescSize);
                        if (status != 0) return FALSE;
                        if (!strcmp( DeviceDescription, NamePtr) ) {
                                DeviceDescSize = 255;
                                status = RegQueryValueEx(HardWareHandle, "SymbolicName",
						 NULL, NULL, (BYTE*)NamePtr, &DeviceDescSize);
                     //should return something like \DosDevices\0000000000000005#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
                                if (status != 0) return FALSE;
                                if ((UINT)LinkNameLen < (UINT) (DeviceDescSize - 12)) 
						return -1;
                                strcat( LinkName, &NamePtr[11]);
                        }

                        status = RegCloseKey(HardWareHandle);
                        
                }
        }
        status = RegCloseKey(KeyHandle);
        return TRUE;

}
As the doctor says, this should also work with 2040/3040 - after camera is set into certain mode.